home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Book Chapters / 03 - Advanced Graphics / Example 3 / demo.c < prev    next >
Text File  |  1995-03-06  |  10KB  |  341 lines

  1. //
  2. //    File: demo.c
  3. //
  4. //    This file contains the routines that control the demo.
  5. //
  6. //    2/19/95 -- Created by Mick
  7. //
  8.  
  9. // include files
  10.  
  11. #include "global.h"
  12.  
  13. #include <Palettes.h>
  14. #include <QDOffscreen.h>
  15.  
  16. #include "demo.h"
  17.  
  18. #include "main.h"
  19. #include "sprite.h"
  20.  
  21. // defines for this file
  22.  
  23. #define kMaxObjects            10                // the maximum number of objects in the demo
  24. #define kClipRectInset        100            // the amount to inset the clip rect
  25.  
  26. // typedefs for this file
  27.  
  28. typedef struct
  29. {
  30.     tSpriteInfo *fSpriteInfo;                                            // the information on the sprite for this object
  31.     unsigned char fIsVisible;                                    // should we draw this object
  32.     signed long fXPos;                                                        // the x position of this object ( 16:16 fixed )
  33.     signed long fYPos;                                                        // the y position of this object ( 16:16 fixed )
  34.     signed long fDeltaX;                                                    // the x coord of the velocity of this object
  35.     signed long fDeltaY;                                                    // the y coord of the velocity of this object
  36. } tObjectInfo;
  37.  
  38. // global function declarations
  39.  
  40. void startupDemo( void );
  41. void shutdownDemo( void );
  42. void demoKey( unsigned char inKey );
  43. void doDemoFrame( void );
  44.  
  45. // global data owned by this file
  46.  
  47. GWorldPtr gOffscreenBuffer;                                        // the port and gdevice of the offscreen buffer
  48. PixMapHandle gOffscreenPixels;                                // the actual pixmap of the offscreen buffer
  49. Rect gOffscreenRect;                                                                // the size of the offscreen buffer
  50.  
  51. // local function declarations
  52.  
  53. static void moveObjects( void );                            // move all the objects
  54. static void blitToScreen( void );                            // copy data from offscreen to onscreen
  55. static void restoreBackground( void );        // redraw the background
  56.  
  57. // static data
  58.  
  59. static tObjectInfo sObjects[ kMaxObjects ];                // the data for all the objects
  60. static unsigned char sClippingFlag;                                    // are we clipping
  61. static Rect sClipRect;                                                                                    // the rect that we are clipping to
  62.  
  63. // functions
  64.  
  65. //
  66. //    startupDemo -
  67. //
  68. //    Create and load all the buffers and data needed for the demo.
  69. //
  70.  
  71. void startupDemo( void )
  72. {
  73.     unsigned short indexCounter;                // a counter to scan the object array
  74.  
  75.     // create the offscreen gworld
  76.     NewGWorld( &gOffscreenBuffer, 8, &( gMainWindow->portRect ), gAppColorTable, ( GDHandle )kNil, keepLocal );
  77.  
  78.     // get the pixel map and rect
  79.     gOffscreenPixels = GetGWorldPixMap( gOffscreenBuffer );
  80.     gOffscreenRect = gMainWindow->portRect;
  81.  
  82.     // load the sprite
  83.     for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
  84.         {
  85.             // load the sprites
  86.             sObjects[ indexCounter ].fSpriteInfo = loadSprite( kNumberOne + indexCounter );
  87.             
  88.             // give it a random location and velocity
  89.             sObjects[ indexCounter ].fXPos = ( Random() & 0x00FF ) << 16;
  90.             sObjects[ indexCounter ].fYPos = ( Random() & 0x00FF ) << 16;
  91.             sObjects[ indexCounter ].fDeltaX = Random() << 4;
  92.             sObjects[ indexCounter ].fDeltaY = Random() << 4;
  93.             
  94.             // initially, it is visible
  95.             sObjects[ indexCounter ].fIsVisible = kTrue;
  96.         }
  97.     
  98.     // determine the clip rect
  99.     sClipRect = gOffscreenRect;
  100.     InsetRect( &sClipRect, kClipRectInset, kClipRectInset );
  101.     
  102.     // set the initial flags
  103.     sClippingFlag = kFalse;
  104. }
  105.  
  106.  
  107. //
  108. //    shutdownDemo -
  109. //
  110. //    Release all the memory used by the demo.
  111. //
  112.  
  113. void shutdownDemo( void )
  114. {
  115.     unsigned short indexCounter;                // a counter to scan the object array
  116.     
  117.     // dump the sprites
  118.     for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
  119.         {
  120.             disposeSprite( sObjects[ indexCounter ].fSpriteInfo );
  121.         }
  122.     
  123.     // dump the offscreen gworld
  124.     DisposeGWorld( gOffscreenBuffer );
  125. }
  126.  
  127.  
  128. //
  129. //    demoKey -
  130. //
  131. //    Handle a key stroke -- allows the user to set options while the demo runs.
  132. //
  133.  
  134. void demoKey( unsigned char inKey )
  135. {
  136.     // depending on the key pressed
  137.     switch( inKey )
  138.         {
  139.             case 'c':        // turn clipping on and off
  140.                 sClippingFlag = !sClippingFlag;
  141.                 break;
  142.             case '1':        // turn this number on and off
  143.                 sObjects[ 0 ].fIsVisible = !sObjects[ 0 ].fIsVisible;
  144.                 break;
  145.             case '2':        // turn this number on and off
  146.                 sObjects[ 1 ].fIsVisible = !sObjects[ 1 ].fIsVisible;
  147.                 break;
  148.             case '3':        // turn this number on and off
  149.                 sObjects[ 2 ].fIsVisible = !sObjects[ 2 ].fIsVisible;
  150.                 break;
  151.             case '4':        // turn this number on and off
  152.                 sObjects[ 3 ].fIsVisible = !sObjects[ 3 ].fIsVisible;
  153.                 break;
  154.             case '5':        // turn this number on and off
  155.                 sObjects[ 4 ].fIsVisible = !sObjects[ 4 ].fIsVisible;
  156.                 break;
  157.             case '6':        // turn this number on and off
  158.                 sObjects[ 5 ].fIsVisible = !sObjects[ 5 ].fIsVisible;
  159.                 break;
  160.             case '7':        // turn this number on and off
  161.                 sObjects[ 6 ].fIsVisible = !sObjects[ 6 ].fIsVisible;
  162.                 break;
  163.             case '8':        // turn this number on and off
  164.                 sObjects[ 7 ].fIsVisible = !sObjects[ 7 ].fIsVisible;
  165.                 break;
  166.             case '9':        // turn this number on and off
  167.                 sObjects[ 8 ].fIsVisible = !sObjects[ 8 ].fIsVisible;
  168.                 break;
  169.             case '0':        // turn this number on and off
  170.                 sObjects[ 9 ].fIsVisible = !sObjects[ 9 ].fIsVisible;
  171.                 break;
  172.             default:        // unknown key
  173.                 SysBeep( 0 );
  174.                 break;
  175.         }
  176. }
  177.  
  178.  
  179. //
  180. //    doDemoFrame -
  181. //
  182. //    Move the demo ahead one frame -- move the sprites and draw.
  183. //
  184.  
  185. void doDemoFrame( void )
  186. {
  187.     CGrafPtr oldPort;                    // the graf port that is in place when we are called
  188.     GDHandle oldDevice;            // the gdevice that is in place when we are called
  189.     signed short indexCounter;            // a counter to scan all the objects
  190.     Rect clipFrame;                            // the rect of the frame to the clipping area
  191.     Point drawPoint;                        // where to draw the sprite
  192.     
  193.     // save the current port and gdevice
  194.     GetGWorld( &oldPort, &oldDevice );
  195.     
  196.     // set the offscreen buffer as current ( and lock the pixel map )
  197.     SetGWorld( gOffscreenBuffer, ( GDHandle )kNil );
  198.     LockPixels( gOffscreenPixels );
  199.     
  200.     // restore the background
  201.     restoreBackground();
  202.     
  203.     // move the objects
  204.     moveObjects();
  205.     
  206.     // setup to draw the shapes (and handle the clipping)
  207.     if ( sClippingFlag )
  208.         {
  209.             clipFrame = sClipRect;
  210.             InsetRect( &clipFrame, -1, -1 );
  211.             FrameRect( &clipFrame );
  212.             startSpriteDraw( &sClipRect, gOffscreenPixels );
  213.         }
  214.     else
  215.         {
  216.             startSpriteDraw( &gOffscreenRect, gOffscreenPixels );
  217.         }
  218.         
  219.     // draw the sprites from back to front
  220.     for( indexCounter = kMaxObjects - 1; indexCounter >= 0; indexCounter-- )
  221.         {
  222.             if ( sObjects[ indexCounter ].fIsVisible )
  223.                 {
  224.                     drawPoint.h = ( sObjects[ indexCounter ].fXPos ) >> 16;
  225.                     drawPoint.v = ( sObjects[ indexCounter ].fYPos ) >> 16;
  226.                     drawSprite( sObjects[ indexCounter ].fSpriteInfo, drawPoint );
  227.                 }
  228.         }
  229.     
  230.     // shutdown the shape draw
  231.     endSpriteDraw();
  232.     
  233.     // copy the buffer to the screen
  234.     blitToScreen();
  235.     
  236.     // restore the current port and gdevice
  237.     UnlockPixels( gOffscreenPixels );
  238.     SetGWorld( oldPort, oldDevice );
  239. }
  240.  
  241.  
  242. //
  243. //    moveObjects -
  244. //
  245. //    Move all the objects.
  246. //
  247.  
  248. void moveObjects( void )
  249. {
  250.     unsigned short indexCounter;            // a counter to scan all the objects
  251.     
  252.     // concider each object
  253.     for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
  254.         {
  255.             // apply the velocity
  256.             sObjects[ indexCounter ].fXPos += sObjects[ indexCounter ].fDeltaX;
  257.             sObjects[ indexCounter ].fYPos += sObjects[ indexCounter ].fDeltaY;
  258.             
  259.             // if the object has hit an edge, bounce it
  260.             if( sObjects[ indexCounter ].fXPos < ( gOffscreenRect.left << 16 ) )
  261.                 {
  262.                     sObjects[ indexCounter ].fDeltaX *= -1;
  263.                     sObjects[ indexCounter ].fXPos += ( gOffscreenRect.left << 16 ) - sObjects[ indexCounter ].fXPos;
  264.                 }
  265.             if( sObjects[ indexCounter ].fYPos < ( gOffscreenRect.top << 16 ) )
  266.                 {
  267.                     sObjects[ indexCounter ].fDeltaY *= -1;
  268.                     sObjects[ indexCounter ].fYPos += ( gOffscreenRect.top << 16 ) - sObjects[ indexCounter ].fYPos;
  269.                 }
  270.             if( sObjects[ indexCounter ].fXPos + 
  271.                     ( ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.right -
  272.                     ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.left ) << 16 ) >
  273.                     ( gOffscreenRect.right << 16 ) )
  274.                 {
  275.                     sObjects[ indexCounter ].fDeltaX *= -1;
  276.                     sObjects[ indexCounter ].fXPos += ( ( gOffscreenRect.right - 
  277.                             ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.right -
  278.                             ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.left ) ) << 16 ) - 
  279.                             sObjects[ indexCounter ].fXPos;
  280.                 }
  281.             if( sObjects[ indexCounter ].fYPos + 
  282.                     ( ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.bottom -
  283.                     ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.top ) << 16 ) >
  284.                     ( gOffscreenRect.bottom << 16 ) )
  285.                 {
  286.                     sObjects[ indexCounter ].fDeltaY *= -1;
  287.                     sObjects[ indexCounter ].fYPos += ( ( gOffscreenRect.bottom - 
  288.                             ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.bottom -
  289.                             ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.top ) ) << 16 ) - 
  290.                             sObjects[ indexCounter ].fYPos;
  291.                 }
  292.         }
  293. }
  294.  
  295.  
  296. //
  297. //    blitToScreen -
  298. //
  299. //    This routine updates the screen from the offscreen buffer.
  300. //
  301.  
  302. void blitToScreen( void )
  303. {
  304.     CGrafPtr oldPort;                    // the graf port that is in place when we are called
  305.     GDHandle oldDevice;            // the gdevice that is in place when we are called
  306.  
  307.     // save the current port and gdevice
  308.     GetGWorld( &oldPort, &oldDevice );
  309.  
  310.     // set the drawing environment to the screen
  311.     SetGWorld( ( CWindowPtr )gMainWindow, GetMainDevice() );
  312.  
  313.     // make sure that the fore and back colors are correct to prevent colorize mode
  314.     ForeColor( blackColor );
  315.     BackColor( whiteColor );
  316.     
  317.     // Copy the screen's color table seed into the source pixmap.
  318.     // This will minimize CopyBits' setup time.
  319.     ( *( ( *gOffscreenPixels )->pmTable ) )->ctSeed = ( *( ( *( ( *( GetGDevice() ) )->gdPMap ) )->pmTable ) )->ctSeed;
  320.  
  321.     // copy the buffer to the screen
  322.     CopyBits( ( BitMap * )( *gOffscreenPixels ), &( gMainWindow->portBits ), 
  323.             &gOffscreenRect, &( gMainWindow->portRect ), 
  324.             srcCopy, ( RgnHandle )kNil );
  325.  
  326.     // restore the current port and gdevice
  327.     SetGWorld( oldPort, oldDevice );
  328. }
  329.  
  330.  
  331. //
  332. //    restoreBackground -
  333. //
  334. //    This routine redraws the background over changed areas.
  335. //
  336.  
  337. void restoreBackground( void )
  338. {
  339.     // erase the entire offscreen
  340.     EraseRect( &gOffscreenRect );
  341. }